//
//		BILBAO
//
//      @name Thread.h
//      @author Bematech S.A.
//

#ifndef __BILBAO_LANG_THREAD_CLASS_H__
#define __BILBAO_LANG_THREAD_CLASS_H__

#include "bilbao/types.h"
#include "bilbao/lang/Mutex.h"

namespace bilbao
{
	namespace lang
	{
		#ifdef BILBAO_THREAD_SUPPORT
			/** Utility macro used to make methods synchronized. How it works:
			 *	- creates a local static mutex;
			 *	- create a locker object for that mutex;
			 *
			 *  What it does:
			 *	- makes things easier :P ;
			 *	- when this macro is called in a function/method, it inserts "mutex-locking code"
			 *	  that controls multiple-thread access in the remaining function/method's code.
			 *
			 *  Typical use for a <em>non-recursive</em> function:
			 *	<pre>
			 *		void mySynhcronizedFunction()
			 *		{
			 *			// let's make this function synchronized
			 *			BILBAO_SYNC
			 *
			 *			// now we can access shared variables safely, like
			 *			// file streams, lists or node position, for example.
			 *			<<Dangerous code here>>
			 *		}
			 *	</pre>
			 */
			#define BILBAO_SYNCHRONIZE						\
				static lang::Mutex localMutex;				\
				lang::MutexLocker localLocker(localMutex);
		#else
			/// In this case, we don't want threading support. :(
			#define BILBAO_SYNCHRONIZE
		#endif

		/// For ease use, we allow lazy users call CGE_SYNC
		#define BILBAO_SYNC BILBAO_SYNCHRONIZE

		/** @brief Defines an interface to be implemented by any class whose instances are intended to be executed as a thread.
		 *
		 *  @remarks
		 *		This interface is designed to provide a common protocol for objects that wish
		 *		to execute code while they are active. Being active simply means that a thread
		 *		has been started and has not yet been stopped.
		 *  @par
		 *		In addition, Runnable provides the means for a class to be active while not
		 *		subclassing Thread. A class that implements Runnable can run without subclassing
		 *		Thread by creating a Thread instance and passing itself in as the target.
		 *
		 *  @see Thread
		 */
		class Runnable
		{
		public:
			/** Destructor (virtual to shut compiler up)
			 */
			virtual ~Runnable() {}

			/** When an object implementing interface Runnable is used
			 *   to create a thread, starting the thread causes the object's <em>run()</em>
			 *	method to be called in that separately executing thread. The contract of the
			 *	method <em>run</em> is that it may take any action whatsoever.
			 *
			 * @see Thread.run()
			 */
			virtual void run(void) = 0;
		};

		/** @brief This class encapsulates a thread, ie, an independent (possibily concurrent) <em>execution thread</em>
		 *
		 *  @remarks
		 *		A Thread is a thread of execution in a program. The engine allows an application to have multiple threads of
		 *		execution running concurrently. Every thread has a priority, so threads with higher priority are executed in
		 *		preference to threads with lower priority. Execution priority can be set by calling setPriority() before the
		 *		thread is started. This class is strongly inpired by Java's class.
		 *  @par
		 *		There are two ways to create a new thread of execution. The most common one is subclassing and overridding
		 *		Thread:run() method. Another way to create a thread is subclassing the Runnable class and passing an instance
		 *		of Runnable to Thread's constructor. This will cause the thread to call the runnable's run() method.
		 *		The second approach only is recomended when a class has more responsibilities than just having methods, but to
		 *		perform some active processing.
		 *	@par
		 *		Thread have the advantage of getting blocked if needed and let the application flow run as if nothing hapenned.
		 *		File loading can be done in background by threads, for example, so application loading gets much faster than if
		 *		it got blocked every time it needs to read/write from/to a file or network. On the other hand, thread concurrency
		 *		can also bring some problems to your applications, by adding read/write access complexity to variables, for example.
		 *		Other problem is that we can't have sweet, synchronized methods like we were programing Java.
		 *	@par
		 *		In addition to threading classes, there were added utility macros and classes. Although C++ does not come with
		 *		native threading support, it haves a nice scheme for doing almost enything by combining OO design and macros.
		 *		Take a look at CGE_SYNCHRONIZE macro and MutexLocker class for multi-threaded programming with less headaches.
		 *
		 *  @see Runnable, Mutex
		 */
		class Thread
		{
		public:
			/// Maximum priority that can be associated with a thread (100)
			static unsigned int PRIORITY_MAX;
			/// Minimum priority that can be associated with a thread (0)
			static unsigned int PRIORITY_MIN;
			/// Priority associated by default for threads
			static unsigned int PRIORITY_NORMAL;

			/** Default constructor
			 */
			Thread(void);

			/** Runnable constructor, providing the means of a class run as thread
			*	without subclassing Thread itself.
			 */
			Thread( Runnable* runnable );

			/** Destructor
			 */
			virtual ~Thread(void);

			/** Sets the priority for this thread
			 *  @remarks Be sure you don't call this method after you call start()
			 *  @see Thread::MAX_PRIORITY, Thread::MIN_PRIORITY, Thread::NORMAL_PRIORITY
			 */
			void setPriority( unsigned int priority );

			/** Gets this thread's priority
			 *  @see Thread::MAX_PRIORITY, Thread::MIN_PRIORITY, Thread::NORMAL_PRIORITY
			 */
			unsigned int getPriority(void) const;

			/** Setups everything and starts this thread, calling the run method
			 *
			 *  This method starts the thread execution.
			 *
			 *  @remarks If you need to set priority, be sure it is done before you call this method.
			 */
			void start(void);

			/** Stops this thread execution
			 */
			void stop(void);

			/** Causes this thread to sleep for the given milliseconds
			 */
			static void sleep( unsigned long milliseconds );

			/** Waits for this thread to stop
			 */
			void wait(void);

			/** The thread frees CPU time if there is nothing to do.
			 */
			void yield(void);

			/**
			 * Shall suspend execution of the calling thread until the target
			 * thread terminates, unless the target thread has already terminated.
			 */
			int join(void);

			/** Checks if this thread is running or not
			 */
			bool isRunning(void) const;

			/** @brief This method will be your thread main method.
			 *  @remarks This method must be implemented, 'cause it will be used as your thread's
			 *			 entry point, action as an OO version for a main() function in a C program.
			 */
			virtual void run(void);

		private:

			/** @brief Private copy-constructor
			 *
			 *  @remarks Threads are not here to be passed by copy as argument nor
			 *			 to be explicitly copied.
			 */
			Thread( const Thread& thread );

			/** @brief Private copy assignment operator
			 *
			 *  @remarks Threads are not here to be passed by copy as argument nor
			 *			 to be explicitly copied.
			 */
			Thread& operator = ( const Thread& thread );

			/** Thread callback used for internal implementation.
			 */
			#if BILBAO_PLATAFORM == BILBAO_WIN32
				static unsigned int __stdcall threadRun(void* param);
			#else
				static void* threadRun (void* param);
			#endif

			/** Is this thread running?
			 */
			bool running;

			/** Is this thread using the runnable interface to provide a run method?
			 */
			Runnable* runnable;

			/** Holds this thread's priority
			 */
			unsigned int priority;

			#if BILBAO_PLATAFORM == BILBAO_WIN32
				/// Win32 thread
				HANDLE thread;
			#else
				/// pthread rulez!!
				pthread_t thread;
			#endif

			/**
			 */
			bool created;
		};
	} // namespace name
} // namespace bilbao

#endif //__BILBAO_LANG_THREAD_CLASS_H__
